package com.yanqu.road.server.manger.activity.snowgarden;

import com.yanqu.road.dao.impl.player.ServerActivityMallDayBuyDaoImpl;
import com.yanqu.road.entity.activity.ActivityConditionInfo;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.ServerActivityMallDayBuyData;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eMailType;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.pb.activity.ServerMallBuyProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.ServerLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.sync.message.SyncResponse;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.checkerframework.checker.linear.qual.Normal;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class MallDayBuyActivity {
    private int activityId;
    //key:userId
    private Map<Long, MallDayBuyUserDayInfo> userDayBuyInfoMap = new ConcurrentHashMap<>();
    //key:day key2:mallId 本服累计购买人数
    private Map<Integer, Map<Integer, Long>> serverDayBuyCountMap = new ConcurrentHashMap<>();
    //key:day key2:mallId 全活动累计购买人数 由跨服同步
    private Map<Integer, Map<Integer, Long>> totalDayBuyCountMap = new ConcurrentHashMap<>();

    private Set<Integer> needSyncDays = new HashSet<>();

    //是否收到过跨服同步消息
    private boolean isReceiveCross = false;


    public MallDayBuyActivity(int activityId) {
        this.activityId = activityId;
        loadDb();
    }

    private void loadDb() {
        Map<Long, MallDayBuyUserDayInfo> tempDayBuyInfoMap = new ConcurrentHashMap<>();
        Map<Integer, Map<Integer, Long>> tempServerDayBuyCountMap = new ConcurrentHashMap<>();
        List<ServerActivityMallDayBuyData> dataList = new ServerActivityMallDayBuyDaoImpl().getServerActivityMallDayBuyDataList(activityId);
        for (ServerActivityMallDayBuyData buyData : dataList) {
            MallDayBuyUserDayInfo userDayInfo = tempDayBuyInfoMap.get(buyData.getUserId());
            if (userDayInfo == null) {
                userDayInfo = new MallDayBuyUserDayInfo(activityId, buyData.getUserId());
                tempDayBuyInfoMap.put(buyData.getUserId(), userDayInfo);
            }
            userDayInfo.addBuyData(buyData);

            Map<Integer, Long> mallBuyMap = tempServerDayBuyCountMap.get(buyData.getDay());
            if (mallBuyMap == null) {
                mallBuyMap = new ConcurrentHashMap<>();
                tempServerDayBuyCountMap.put(buyData.getDay(), mallBuyMap);
            }
            Long oldNum = mallBuyMap.getOrDefault(buyData.getMallId(), 0L);
            oldNum++;
            mallBuyMap.put(buyData.getMallId(), oldNum);
        }
        userDayBuyInfoMap = tempDayBuyInfoMap;
        serverDayBuyCountMap = tempServerDayBuyCountMap;
    }

    public void save() {
        List<MallDayBuyUserDayInfo> tempDayInfoList = new ArrayList<>();
        synchronized (userDayBuyInfoMap) {
            tempDayInfoList.addAll(userDayBuyInfoMap.values());
        }
        for (MallDayBuyUserDayInfo dayInfo : tempDayInfoList) {
            dayInfo.save();
        }
    }

    public MallDayBuyUserDayInfo getUserDayBuyInfoNewIfNull(long userId) {
        MallDayBuyUserDayInfo userDayInfo = userDayBuyInfoMap.get(userId);
        if (userDayInfo == null) {
            synchronized (userDayBuyInfoMap) {
                userDayInfo = userDayBuyInfoMap.get(userId);
                if (userDayInfo == null) {
                    userDayInfo = new MallDayBuyUserDayInfo(activityId, userId);
                    userDayBuyInfoMap.put(userId, userDayInfo);
                }
            }
        }
        return userDayInfo;
    }

    public void addMallBuy(long userId, int mallId) {
        ActivityInfo openActivityInfo = ActivityMgr.getOpenActivityInfo(activityId);
        if (openActivityInfo == null) {
            return;
        }
        int activityDay = ActivityHelper.getWhichDayAfterBeginTime(openActivityInfo);
        if (activityDay <= 0) {
            return;
        }
        boolean needAddTotalServerNum = false;
        MallDayBuyUserDayInfo userDayInfo = getUserDayBuyInfoNewIfNull(userId);
        if(!userDayInfo.isUserTodayBuyMall(activityDay, mallId)){
            needAddTotalServerNum = true;
        }
        userDayInfo.addMallBuy(activityDay, mallId);

        if (needAddTotalServerNum){// 之前没有本服购买记录,才更新全服累计
            synchronized (serverDayBuyCountMap) {
                Map<Integer, Long> mallBuyMap = serverDayBuyCountMap.get(activityDay);
                if (mallBuyMap == null) {
                    mallBuyMap = new ConcurrentHashMap<>();
                    serverDayBuyCountMap.put(activityDay, mallBuyMap);
                }
                Long oldNum = mallBuyMap.getOrDefault(mallId, 0L);
                oldNum++;
                mallBuyMap.put(mallId, oldNum);
            }

            //直接先更新全服累计,更新成就
            addActivityTotalCount(activityDay, mallId, 1);

            synchronized (needSyncDays) {
                needSyncDays.add(activityDay);
            }
        }
    }

    public Map<Integer, Long> getServerDayBuyNum(int day) {
        Map<Integer, Long> tempMap = new HashMap<>();
        synchronized (serverDayBuyCountMap) {
            Map<Integer, Long> mallBuyMap = serverDayBuyCountMap.get(day);
            if (mallBuyMap != null) {
                tempMap.putAll(mallBuyMap);
            }
        }
        return tempMap;
    }

    public void syncServerBuyCount() {
        if (needSyncDays.isEmpty()) {
            return;
        }

        List<Integer> days = new ArrayList<>();
        synchronized (needSyncDays) {
            if (needSyncDays.isEmpty()) {
                return;
            }
            days.addAll(needSyncDays);
            needSyncDays.clear();
        }

        List<ServerMallBuyProto.DayBuyDataTemp> tempList = new ArrayList<>();
        for (Integer day : days) {
            Map<Integer, Long> serverDayBuyNum = getServerDayBuyNum(day);
            for (Map.Entry<Integer, Long> entry : serverDayBuyNum.entrySet()) {
                int mallId = entry.getKey();
                Long buyNum = entry.getValue();

                ServerMallBuyProto.DayBuyDataTemp.Builder tempBuilder = ServerMallBuyProto.DayBuyDataTemp.newBuilder();
                tempBuilder.setDay(day);
                tempBuilder.setMallId(mallId);
                tempBuilder.setNewCount(buyNum);
                tempList.add(tempBuilder.build());
            }
        }

        if (tempList.isEmpty()) {
            return;
        }

        // 发到跨服
        ServerMallBuyProto.ServerMallBuyToCrossSyncMsg.Builder syncMsg = ServerMallBuyProto.ServerMallBuyToCrossSyncMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.addAllServerBuyData(tempList);

        CompletableFuture<SyncResponse> responseFuture = GamePlayerMgr.sendToActivityCrossServer(0, CrossProtocol.C_SEVER_MALL_BUY_ADD, activityId, syncMsg, null);
        responseFuture.thenAccept(response -> {
            if (response.getErrorCode() != 0) {
                ActivityMallDayBuyMgr.getLogger().error("syncServerBuyCount error, activityId:{}, errorCode:{}", activityId, response.getErrorCode());
                //超时继续压入队列等待发送
                for (ServerMallBuyProto.DayBuyDataTemp temp : syncMsg.getServerBuyDataList()) {
                    synchronized (needSyncDays) {
                        needSyncDays.add(temp.getDay());
                    }
                }
            }
        });
    }

    public void updateActivityTotalCount(int day, int mallId, long buyNum) {
        synchronized (totalDayBuyCountMap) {
            Map<Integer, Long> mallBuyMap = totalDayBuyCountMap.get(day);
            if (mallBuyMap == null) {
                mallBuyMap = new ConcurrentHashMap<>();
                totalDayBuyCountMap.put(day, mallBuyMap);
            }
            mallBuyMap.put(mallId, buyNum);
        }
    }

    private void addActivityTotalCount(int day, int mallId, long buyNum) {
        synchronized (totalDayBuyCountMap) {
            Map<Integer, Long> mallBuyMap = totalDayBuyCountMap.get(day);
            if (mallBuyMap == null) {
                mallBuyMap = new ConcurrentHashMap<>();
                totalDayBuyCountMap.put(day, mallBuyMap);
            }
            Long newNum = mallBuyMap.getOrDefault(mallId, 0L);
            newNum += buyNum;
            mallBuyMap.put(mallId, newNum);
        }

        for (GamePlayer gamePlayer : GamePlayerMgr.getAllOnlinePlayer()) {
            gamePlayer.notifyListener(eGamePlayerEventType.SeasonServerMallBuyTask.getValue());
        }
    }

    public void queryActivityTotalCountTask() {
        //内存里没有总的进度数据才请求,然后被动等待跨服同步
        if (!totalDayBuyCountMap.isEmpty()) {
            return;
        }
        if (isReceiveCross) {
            return;
        }
        ServerMallBuyProto.ServerQueryMallTotalBuyReqMsg.Builder reqMsg = ServerMallBuyProto.ServerQueryMallTotalBuyReqMsg.newBuilder();
        reqMsg.setActivityId(activityId);
        GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(CrossProtocol.C_SEVER_MALL_BUY_GET_DAY_BUY_DATA, reqMsg.build()));
    }

    public boolean isUserTodayBuyMall(int whichDay, long userId, int mallId) {
        MallDayBuyUserDayInfo mallDayBuyUserDayInfo = userDayBuyInfoMap.get(userId);
        if (mallDayBuyUserDayInfo == null) {
            return false;
        }
        return mallDayBuyUserDayInfo.isUserTodayBuyMall(whichDay, mallId);
    }

    public long getTotalDayBuyCount(int day, int mallId) {
        Map<Integer, Long> mallBuyMap = totalDayBuyCountMap.get(day);
        if (mallBuyMap == null) {
            return 0;
        }
        return mallBuyMap.getOrDefault(mallId, 0L);
    }

    public void updateGetConditionReward(int day, long userId, int mallId, int conditionId) {
        MallDayBuyUserDayInfo userDayBuyInfo = getUserDayBuyInfoNewIfNull(userId);
        if (userDayBuyInfo == null) {
            return;
        }
        MallDayBuyUserMallInfo userDayMallInfo = userDayBuyInfo.getUserDayMallInfoNewIfNull(day);
        if (userDayMallInfo == null) {
            return;
        }

        ServerActivityMallDayBuyData userDayBuyData = userDayMallInfo.getUserDayMallInfoNewIfNull(mallId);
        if (userDayBuyData == null) {
            return;
        }

        Set<Integer> awardConditionIdList = userDayBuyData.getAwardConditionIdList();
        if (awardConditionIdList.contains(conditionId)) {
            ActivityMallDayBuyMgr.getLogger().error("玩家{},conditionId={} ,重复领奖！！！", userId, conditionId);
            return;
        }
        userDayBuyData.addAwardConditionId(conditionId);

    }

    /**
     * 自动补发
     *
     * @param crossBuyDataList
     */
    public void autoReward(List<ServerMallBuyProto.DayBuyDataTemp> crossBuyDataList) {
        ActivityInfo openActivityInfo = ActivityMgr.getOpenActivityInfo(activityId);
        if (openActivityInfo == null) {
            ActivityMallDayBuyMgr.getLogger().error("activityId:{} not open", activityId);
            return;
        }
        Map<Integer, List<ActivityConditionInfo>> activityConditionInfoListMap = NormalActivityMgr.getActivityConditionInfoMallKeyMapByType(activityId, eGamePlayerEventType.SeasonServerMallBuyTask.getValue());

        Map<Long, List<ActivityConditionInfo>> userNeedAutoMailMap = new HashMap<>();//玩家需要补发的活动数据

        for (ServerMallBuyProto.DayBuyDataTemp temp : crossBuyDataList) {
            int day = temp.getDay();
            int mallId = temp.getMallId();
            long conditionCheckValue = temp.getNewCount();
            MallInfo activityMallInfo = NormalActivityMgr.getActivityMallInfo(activityId, mallId);
            if (activityMallInfo == null) {
                ActivityMallDayBuyMgr.getLogger().error("activityId:{},mallId:{} not exist", activityId, mallId);
                continue;
            }
            int mallKey = Integer.parseInt(activityMallInfo.getExtendParam());
            //从配置里找到满足条件的condition
            List<ActivityConditionInfo> activityConditionInfos = activityConditionInfoListMap.get(mallKey);
            if (activityConditionInfos == null) {
                ActivityMallDayBuyMgr.getLogger().error("activityId:{},mallId:{},mallKey:{} condition not exist", activityId, mallId, mallKey);
                continue;
            }

            for (ActivityConditionInfo activityConditionInfo : activityConditionInfos) {
                long valueNeed = activityConditionInfo.getParamList().get(3).longValue();
                if (conditionCheckValue < valueNeed) {
                    continue;
                }
                //满足条件的奖励
                List<ServerActivityMallDayBuyData> serverDayBuyData = getAllDayBuyDataMapByDayAndMallId(day, mallId);
                for (ServerActivityMallDayBuyData dayBuyData : serverDayBuyData) {
                    if (dayBuyData.getAwardConditionIdList().contains(activityConditionInfo.getConditionId())) {//已经领奖了
                        continue;
                    }
                    //这里先设置进去,防止重复补发
                    dayBuyData.addAwardConditionId(activityConditionInfo.getConditionId());

                    //没领奖的要补发
                    List<ActivityConditionInfo> needAutoMailInfos = userNeedAutoMailMap.get(dayBuyData.getUserId());
                    if (needAutoMailInfos == null) {
                        needAutoMailInfos = new ArrayList<>();
                        userNeedAutoMailMap.put(dayBuyData.getUserId(), needAutoMailInfos);
                    }
                    needAutoMailInfos.add(activityConditionInfo);
                }
            }
        }

        for (Map.Entry<Long, List<ActivityConditionInfo>> entry : userNeedAutoMailMap.entrySet()) {
            long userId = entry.getKey();
            Property mailReward = new Property();
            for (ActivityConditionInfo activityConditionInfo : entry.getValue()) {
                mailReward.addProperty(activityConditionInfo.getReward());
            }
//            if (mailReward.isNothing()) {
//                continue;
//            }
            //  发邮件
            String language = UserMgr.getLanguage(userId);
            String activityName = ActivityMgr.getActivityName(openActivityInfo, language);
            String mailTitle;
            String mailContent;
            if(openActivityInfo.getType() == eActivityType.SummerGames.getValue()){
                mailTitle = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.SUMMER_GAMES_MAIL_TITLE_2, language), activityName);
                mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.SUMMER_GAMES_CONTENT_2, language), activityName);
            } else if (openActivityInfo.getType() == eActivityType.SnowGarden.getValue()) {
                mailTitle = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.SNOW_GARDEN_MAIL_TITLE_2, language), activityName);
                mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.SNOW_GARDEN_MAIL_CONTENT_2, language), activityName);
            } else {
                mailTitle = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.GROUP_BUY_MAIL_TITLE, language), activityName);
                mailContent = StringUtils.format(MultipleLanguageMgr.getContent(MailManager.GROUP_BUY_MAIL_CONTENT, language), activityName);
            }
            MailManager.sendMail(userId, eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(mailReward), mailContent, mailTitle);
        }
    }

    public boolean isReceiveCross() {
        return isReceiveCross;
    }

    public void setReceiveCross(boolean receiveCross) {
        isReceiveCross = receiveCross;
    }

    public List<ServerActivityMallDayBuyData> getAllDayBuyDataMapByDayAndMallId(int day, int mallId) {
        List<ServerActivityMallDayBuyData> dataList = new ArrayList<>();
        synchronized (userDayBuyInfoMap) {
            for (MallDayBuyUserDayInfo userDayBuyInfo : userDayBuyInfoMap.values()) {
                MallDayBuyUserMallInfo userDayMallInfo = userDayBuyInfo.getDayInfo(day);
                if (userDayMallInfo == null) {
                    continue;
                }
                ServerActivityMallDayBuyData dayBuyData = userDayMallInfo.getDayBuyData(mallId);
                if (dayBuyData == null) {
                    continue;
                }
                dataList.add(dayBuyData);
            }
        }
        return dataList;
    }

    /**
     * 修复或打印用的接口
     * @param params
     */
    public void repair(String params) {

    }

    public int getActivityId() {
        return activityId;
    }
}
